Imports Microsoft.DirectX

Namespace GUI

    Friend Class MirText
        Implements Windows.GUIObj

        'properties:
        'textstring
        '

        Dim mWnd As MirWindow
        Dim mName As String
        Dim mToolTipText As String

        Public mPosX As Integer, mPosY As Integer
        Dim mXMargin As Integer, mYMargin As Integer
        Dim mBackColor As Color
        Dim mBorderColor As Color
        Dim mFont As Fonts.MirFont
        Dim mText As String = ""

        Dim mMaxWidth As Integer
        Dim mMinWidth As Integer
        Dim mBoxRect As Rectangle
        Dim mTextRect As Rectangle

        Dim mBoldHeightDiff As Integer

        Dim mIsVisible As Boolean

        Dim mColors As ArrayList
        Dim mHoverCol As Color

        Dim textTexture As Direct3D.Texture
        Dim textSurface As Direct3D.Surface
        Dim rhlper As Direct3D.RenderToSurface
        Dim needstextrefresh As Boolean

        Public Event TabSwitch() Implements Windows.GUIObj.TabSwitch
        Public Event Click(name As String)

        Dim mCaptureClicks As Boolean
        Dim mDefaultZ As Single

        Public Sub New(ByRef wnd As MirWindow, ByRef name As String, ByRef x As Integer, ByRef y As Integer, _
        ByRef font As Fonts.MirFont, ByRef sTextString As String, ByRef colBackground As Color, ByRef colBorder As Color, _
        ByRef arColors As ArrayList, Optional ByRef xMargin As Integer = 0, Optional ByRef yMargin As Integer = 0, _
        Optional ByRef minLineWidth As Integer = 0, Optional ByRef maxLineWidth As Integer = 0, Optional ByRef captureclicks As Boolean = False, Optional ByRef defaultz As Single = 2.0F, Optional ByRef hoverCol As Color = Nothing)

            mWnd = wnd
            mName = name
            mPosX = x
            mPosY = y
            mXMargin = xMargin
            mYMargin = yMargin

            mBackColor = colBackground
            mBorderColor = colBorder
            mColors = arColors
            mHoverCol = hoverCol

            mText = sTextString
            mFont = font

            mMinWidth = minLineWidth
            mMaxWidth = maxLineWidth
            mDefaultZ = defaultz
            CalcClientRect()

            needstextrefresh = True

            mIsVisible = True

            mCaptureClicks = captureclicks

            wnd.AddInterfaceItem(Me)

        End Sub

        Public Sub MouseInput(ByRef type As Mouse.MouseInputType, ByRef e As MouseEventArgs) Implements Windows.GUIObj.MouseInput

            Select Case type

                Case Mouse.MouseInputType.MouseClick
                    If mCaptureClicks Then RaiseEvent Click(mName)

            End Select

        End Sub

        Private Sub CalcClientRect(Optional ByVal skiptex As Boolean = False)

            'set mboxrect and mtextrect

            Dim tmpStr As String, tmpSize As Size
            Dim width As Integer
            Dim height As Integer
            Dim i As Integer = 1, p As Integer

            Do Until p = mText.Length

                p = InStr(i, mText, "\n")
                If p = 0 Then p = mText.Length
                tmpStr = Mid(mText, i, p - i)
                tmpSize = CalcSize(tmpStr)

                If mMaxWidth > 0 Then
                    If tmpSize.Width > mMaxWidth Then
                        InsertSplit(mText, i)
                        CalcClientRect(skiptex)
                        Exit Sub
                    End If
                End If

                If width < tmpSize.Width Then width = tmpSize.Width
                height += tmpSize.Height
                i = p + 2

            Loop

            mTextRect = New Rectangle(mPosX + mXMargin, mPosY + mYMargin, width, height) 'mPosX + mXMargin + width, mPosY + mYMargin + height)
            mBoxRect = New Rectangle(mPosX, mPosY, width + (mXMargin * 2), height + (mYMargin * 2)) 'mPosX + (mXMargin * 2) + width, mPosY + (mYMargin * 2) + height)

            mBoldHeightDiff = mFont.GetBoldTextHeight("X") - mFont.GetNormalTextHeight("X")

            If Not skiptex Then

                If Not textTexture Is Nothing Then
                    textTexture.Dispose()
                    textSurface.Dispose()
                End If

                textTexture = New Direct3D.Texture(DirectX.D3D, width + (mXMargin * 2) + 64, height + (mYMargin * 2) + 64, 1, Direct3D.Usage.RenderTarget, DirectX.ColorFormat, Direct3D.Pool.Default)
                textSurface = textTexture.GetSurfaceLevel(0)

                needstextrefresh = True

            End If

        End Sub

        Private Sub InsertSplit(ByRef str As String, ByRef start As Integer)

            Dim p As Integer = start, lastp As Integer

            Do

                If Mid(str, p, 1) = "\" Then
                    p += 1
                Else
                    If CalcSize(Mid(str, start, (p - start) + 1)).Width > mMaxWidth Then
                        p = lastp
                        Do Until p = start Or Mid(str, p, 1) = " "
                            p -= 1
                        Loop
                        If p <> start Then lastp = p
                        str = Left(str, lastp) & "\n" & Right(str, Len(str) - lastp)
                        Exit Sub
                    Else
                        lastp = p
                    End If
                End If

                p += 1

            Loop

        End Sub

        Private Function CalcSize(ByRef str As String) As Size

            Dim i As Integer ', p As Integer
            Dim tmpStr As String = ""
            Dim width As Integer, height As Integer = 0
            Dim tmp As Integer
            Dim isbold As Boolean
            Dim ignoreprevslash As Boolean

            For i = 0 To str.Length - 1
                If str.Chars(i) <> "\" Then
                    If i > 0 Then
                        If str.Chars(i - 1) <> "\" Or ignoreprevslash Then
                            tmpStr &= str.Chars(i)
                            ignoreprevslash = False
                        Else
                            If str.Chars(i) = "b" Then
                                width += GetFontWidth(tmpStr, isbold)
                                tmp = GetFontHeight(tmpStr, isbold)
                                If height < tmp Then height = tmp
                                tmpStr = ""
                                isbold = Not (isbold)
                            End If
                        End If
                    Else
                        tmpStr &= str.Chars(i)
                    End If
                ElseIf i > 0 Then
                    If (str.Chars(i) = "\" And str.Chars(i - 1) = "\") Then
                        tmpStr &= "\"
                        ignoreprevslash = True
                    End If
                End If
            Next

            width += GetFontWidth(tmpStr, isbold)
            tmp = GetFontHeight(tmpStr, isbold)
            If height < tmp Then height = tmp
            If width < mMinWidth Then width = mMinWidth

            Return New Size(width, height)

        End Function

        Private Function GetFontWidth(ByRef str As String, ByRef isbold As Boolean) As Integer

            If str = "" Then str = "X"

            If isbold Then
                Return mFont.GetBoldTextWidth(str) - 1
            Else
                Return mFont.GetNormalTextWidth(str) - 1
            End If

        End Function

        Private Function GetFontHeight(ByRef str As String, ByRef isbold As Boolean) As Integer

            If str = "" Then str = "X"

            If isbold Then
                Return mFont.GetBoldTextHeight(str)
            Else
                Return mFont.GetNormalTextHeight(str)
            End If

        End Function

        Public Function Contains(ByRef x As Integer, ByRef y As Integer) As Boolean Implements Windows.GUIObj.Contains

            If Not mIsVisible Then Return False
            If Not mCaptureClicks Then Return False
            Return mBoxRect.Contains(x, y)

        End Function

        Private refreshtimeout As DateTime = DateTime.Now

        Public Sub Draw(ByRef mode As Globals.DrawingMode, ByRef x As Integer, ByRef y As Integer, ByRef z As Single) Implements Windows.mWindows.GUIObj.Draw

            If Not mIsVisible Then Exit Sub

            If mText.Length = 0 Then Exit Sub

            If mCaptureClicks And refreshtimeout < DateTime.Now Then
                needstextrefresh = True
                refreshtimeout = DateTime.Now.AddMilliseconds(500)
            End If


            If mode = Globals.DrawingMode.Overlay And needstextrefresh Then


                DirectX.D3D.SetRenderTarget(0, textSurface)

                DirectX.D3D.BeginScene()

                DirectX.D3D.Clear(Microsoft.DirectX.Direct3D.ClearFlags.Target Or Microsoft.DirectX.Direct3D.ClearFlags.ZBuffer, Color.Transparent, 1.0, 0)

                Engine.UseLineShader()
                DirectX.D3D.VertexFormat = Microsoft.DirectX.Direct3D.CustomVertex.TransformedColored.Format

                Dim tmp As Rectangle = mBoxRect
                tmp.Offset(-mPosX, -mPosY)
                Engine.DrawSolidBox(tmp, z, mBackColor)
                Engine.DrawBox(tmp, z, 1, mBorderColor)

                Engine.ResetShader()

                Engine.SetDrawModeNormal(1.0, Color.White)

                Dim i As Integer
                Dim tmpStr As String = ""
                Dim isbold As Boolean, hover As Boolean, dblslash As Boolean
                Dim col As Integer
                Dim px As Integer, py As Integer

                px = mXMargin
                py = mYMargin

                If mCaptureClicks And mTextRect.Contains(Mouse.XCoord - x, Mouse.YCoord - y) Then
                    hover = True
                End If

                'itterate through every char in text string
                For i = 0 To mText.Length - 1
                    'if this doesnt mark a symbol
                    If mText.Chars(i) <> "\" Then
                        'if index isnt first one
                        If i > 0 Then
                            'if previous char doesnt mark symbol
                            If mText.Chars(i - 1) <> "\" or dblslash Then
                                tmpStr &= mText.Chars(i)
                                dblslash = False
                            Else
                                'previous char marks symbol
                                'if we have text waiting to be drawn draw it
                                If tmpStr.Length > 0 Then
                                    DrawText(tmpStr, px, py, col, isbold, z, hover)
                                    px += (GetFontWidth(tmpStr, isbold) / (tmpStr.Length + 1)) * tmpStr.Length + 2
                                    tmpStr = ""
                                End If
                                'check for color notation
                                If IsNumeric(mText.Chars(i)) Then
                                    col = mText.Chars(i).ToString
                                    'check for bold symbo;l
                                ElseIf mText.Chars(i) = "b" Then
                                    isbold = Not (isbold)
                                ElseIf mText.Chars(i) = "n" Then
                                    py += mFont.GetBoldTextHeight("X")
                                    px = mXMargin
                                End If
                            End If
                        Else
                            tmpStr &= mText.Chars(i)
                        End If
                    ElseIf i > 0 Then
                        If mText.Chars(i) = "\" And mText.Chars(i - 1) = "\" Then
                            tmpStr &= "\"
                            dblslash = True
                        End If
                    End If
                Next

                DrawText(tmpStr, px, py, col, isbold, z, hover)

                needstextrefresh = False

                DirectX.D3D.EndScene()

            ElseIf mode = Globals.DrawingMode.Tooltip And mIsVisible Then

                If mDefaultZ = 2.0F Then
                    DirectX.BlitD3D(textTexture, x + mPosX, y + mPosY, Width + (mXMargin * 2) + 4, Height + (mYMargin * 2) + 4, z)
                Else
                    DirectX.BlitD3D(textTexture, x + mPosX, y + mPosY, Width + (mXMargin * 2) + 4, Height + (mYMargin * 2) + 4, mDefaultZ)
                End If

            End If

        End Sub

        Private Sub DrawText(ByRef txt As String, ByRef x As Integer, ByRef y As Integer, ByRef col As Integer, ByRef bold As Boolean, ByRef z As Single, Optional hover As Boolean = False)
            If bold Then
                mFont.DrawBoldBorderTextEx(txt, x, y, mColors(col), Color.Black, z)
            Else
                If hover Then
                    mFont.DrawBorderTextEx(txt, x, y + mBoldHeightDiff, mHoverCol, Color.Black, z)
                Else
                    mFont.DrawBorderTextEx(txt, x, y + mBoldHeightDiff, mColors(col), Color.Black, z)
                End If
            End If
        End Sub

        Public Sub SetColorList(ByRef cols As ArrayList)

            mColors = cols

        End Sub

        Public Property TextString() As String
            Get
                Return mText
            End Get
            Set(ByVal value As String)
                If mText <> value Then
                    mText = value
                    CalcClientRect()
                    needstextrefresh = True
                End If
            End Set
        End Property

        Public Property Visible() As Boolean
            Get
                Return mIsVisible
            End Get
            Set(ByVal value As Boolean)
                mIsVisible = value
            End Set
        End Property

        Public Sub Focus() Implements Windows.mWindows.GUIObj.Focus

        End Sub

        Public Sub KeyboardInput(ByRef type As Keyboard.mKeyboardVars.KeyboardInputType, ByRef e As System.Windows.Forms.KeyEventArgs) Implements Windows.mWindows.GUIObj.KeyboardInput

        End Sub

        Public Sub KeyboardInput(ByRef type As Keyboard.mKeyboardVars.KeyboardInputType, ByRef e As System.Windows.Forms.KeyPressEventArgs) Implements Windows.mWindows.GUIObj.KeyboardInput

        End Sub

        Public Sub UnFocus() Implements Windows.mWindows.GUIObj.UnFocus

        End Sub

        Public Sub Destroy() Implements Windows.mWindows.GUIObj.Destroy
            mWnd.RemoveInterfaceItem(Me)
            If Not textTexture Is Nothing Then
                textTexture.Dispose()
                textSurface.Dispose()
            End If
        End Sub

        Public ReadOnly Property GetsFocus() As Boolean Implements Windows.mWindows.GUIObj.GetsFocus
            Get
                Return False
            End Get
        End Property

        Public Sub SetPos(ByRef x As Integer, ByRef y As Integer) Implements Windows.mWindows.GUIObj.SetPos
            If mPosX = x And mPosY = y Then Exit Sub
            mPosX = x
            mPosY = y
            CalcClientRect(True)
        End Sub

        Public ReadOnly Property Width() As Integer
            Get
                Return mBoxRect.Width
            End Get
        End Property

        Public ReadOnly Property Height() As Integer
            Get
                Return mBoxRect.Height
            End Get
        End Property

        Public ReadOnly Property ParentWin() As MirWindow Implements Windows.mWindows.GUIObj.ParentWin
            Get
                Return mWnd
            End Get
        End Property

        Public ReadOnly Property Name() As String Implements Windows.mWindows.GUIObj.Name
            Get
                Return mName
            End Get
        End Property

        Public Sub ReloadSurafces() Implements Windows.mWindows.GUIObj.ReloadSurafces

            If Not textTexture Is Nothing Then

                textTexture.Dispose()
                textSurface.Dispose()

            End If

            textTexture = New Direct3D.Texture(DirectX.D3D, Width + (mXMargin * 2) + 16, Height + (mYMargin * 2) + 16, 1, Direct3D.Usage.RenderTarget, DirectX.ColorFormat, Direct3D.Pool.Default)
            textSurface = textTexture.GetSurfaceLevel(0)
            mFont = DirectX.ProFont9
            needstextrefresh = True
        End Sub
    End Class

End Namespace
